package com.deppon.vts.data.plugin;

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import org.apache.ibatis.cache.Cache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import org.springframework.util.SerializationUtils;

import redis.clients.jedis.Jedis;

public class MyBatisRedisCache implements Cache{
	
	private String id;
	
	private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
	
	private static Logger log = LoggerFactory.getLogger(MyBatisRedisCache.class);
	
	public MyBatisRedisCache(final String id){
		if(id == null){
			throw new IllegalArgumentException("MyBatisRedisCache initialized failed. No id has provided.");
		}
		if(log.isDebugEnabled())
			log.debug("MyBatisRedisCache initailized with id: {}", id);
		this.id = id;
	}

	@Override
	public String getId() {
		return id;
	}

	@Override
	public void putObject(Object key, Object value) {
		Jedis jedis = JedisFactory.getJedis();
		Assert.notNull(jedis);
		Assert.notNull(key);
		if(value == null)
			return;
		jedis.set(SerializationUtils.serialize(key), SerializationUtils.serialize(value));
		if(log.isDebugEnabled())
			log.debug("MyBatisRedisCache add {}:{}", key, value);
		JedisFactory.returnResource(jedis);
	}

	@Override
	public Object getObject(Object key) {
		Jedis jedis = JedisFactory.getJedis();
		Assert.notNull(jedis);
		Assert.notNull(key);
		Object value = SerializationUtils.deserialize(jedis.get(SerializationUtils.serialize(key.toString())));
		if(log.isDebugEnabled())
			log.debug("MyBatisRedisCache get {}:{}", key, value);
		JedisFactory.returnResource(jedis);
	    return value;
	}

	@Override
	public Object removeObject(Object key) {
		Jedis jedis = JedisFactory.getJedis();
		Assert.notNull(jedis);
		Assert.notNull(key);
		if(log.isDebugEnabled())
			log.debug("MyBatisRedisCache remove key:{}", key);
		long removeCount = jedis.expire(SerializationUtils.serialize(key.toString()), 0);
		JedisFactory.returnResource(jedis);
		return removeCount;
	}

	@Override
	public void clear() {
		Jedis jedis = JedisFactory.getJedis();
		Assert.notNull(jedis);
		jedis.flushDB();
		if(log.isDebugEnabled())
			log.debug("MyBatisRedisCache flush db.");
		JedisFactory.returnResource(jedis);
	}

	@Override
	public int getSize() {
		Jedis jedis = JedisFactory.getJedis();
		Assert.notNull(jedis);
		return Integer.valueOf(jedis.dbSize().toString());
	}

	@Override
	public ReadWriteLock getReadWriteLock() {
		return readWriteLock;
	}
	
}
